package com.crois.barrier.admin.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.crois.barrier.admin.entity.*;
import com.crois.barrier.admin.enums.PositionTypeEnum;
import com.crois.barrier.common.dto.IpBlackWhite;
import com.crois.barrier.common.exception.BarrierException;
import com.crois.barrier.common.exception.BarrierExceptionEnum;
import com.zhimydou.ztools.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author: HouZeYu
 * @Description:
 * @Date: Created in 17:42 2021/11/4
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class NacosConfigSvc implements INaocsConfigSvc {

   @Autowired
   private ConfigService configService;

    protected static final String group = "DEFAULT_GROUP";

    protected static final String pluginDataId = "barrier.plugin.json";

    protected static final String authRouteId = "barrier.route.json";

    protected static final String ip_black_white_Id = "barrier.black.white.json";

    @Autowired
    @Qualifier("apiRouteInfoSvc")
    private IApiRouteInfoSvc apiRouteInfoSvc;

    @Autowired
    @Qualifier("apiRouteGroupSvc")
    private IApiRouteGroupSvc apiRouteGroupSvc;

    @Autowired
    @Qualifier("apiParameterInfoSvc")
    private IApiParameterInfoSvc apiParameterInfoSvc;

    @Autowired
    @Qualifier("apiResponseInfoSvc")
    private IApiResponseInfoSvc apiResponseInfoSvc;

    @Autowired
    @Qualifier("apiFailCodeInfoSvc")
    private IApiFailCodeInfoSvc apiFailCodeInfoSvc;
    @Autowired
    @Qualifier("ipAndWeightSvc")
    private IIpAndWeightSvc ipAndWeightSvc;

    @Autowired
    @Qualifier("pluginDataSvc")
    private IPluginDataSvc pluginDataSvc;

    @Autowired
    @Qualifier("ipBlackWhiteSvc")
    private IIpBlackWhiteSvc ipBlackWhiteSvc;

    @Override
    public void pushApiRoute() {
        List<ApiRouteInfo> apiRouteInfoListDb = apiRouteInfoSvc.findApiRouteList(null,null);
        List<ApiRouteInfo> apiRouteInfoList = new ArrayList<>();
        for (ApiRouteInfo routeInfo : apiRouteInfoListDb) {
            ApiRouteInfo apiRouteInfo = apiRouteInfoSvc.getById(routeInfo.getId());
            List<IpAndWeight> ipAndWeightList = ipAndWeightSvc.getIpAndWeightListByRouteId(apiRouteInfo.getId());
            apiRouteInfo.setIpList(ipAndWeightList);
            ApiRouteGroup apiRouteGroup = apiRouteGroupSvc.getById(apiRouteInfo.getApiRouteGroupId());
            apiRouteInfo.setApiGroupName(apiRouteGroup.getApiRouteGroupName());
            List<ApiParameterInfo> apiParameterInfoList = apiParameterInfoSvc.findApiParameterListByRouteIdAndType(PositionTypeEnum.API_PARAMETER.getType(),apiRouteInfo.getId());
            apiRouteInfo.setApiParameter(apiParameterInfoList);
            List<ApiParameterInfo> constantsParameterInfoList = apiParameterInfoSvc.findApiParameterListByRouteIdAndType(PositionTypeEnum.CONSTANTS.getType(),apiRouteInfo.getId());
            apiRouteInfo.setConstantsParameter(constantsParameterInfoList);
            ApiResponseInfo apiResponseInfo = apiResponseInfoSvc.findApiResponseInfoByRouteId(apiRouteInfo.getId());
            if (!Objects.isNull(apiResponseInfo)){
                List<ApiFailCodeInfo> apiFailCodeInfoList =  apiFailCodeInfoSvc.findApiFailCodeInfoListByApiResponseInfoId(apiResponseInfo.getId());
                apiResponseInfo.setApiFailCodeInfoList(apiFailCodeInfoList);
            }
            apiRouteInfo.setApiResponse(apiResponseInfo);
            List<PluginData> routePluginList = pluginDataSvc.findRoutePluginList(apiRouteInfo.getId());
            if (CollectionUtil.isNotEmpty(routePluginList)){
                List<String> plugins = routePluginList.stream().map(PluginData::getName).collect(Collectors.toList());
                apiRouteInfo.setPlugins(plugins);
            }
            apiRouteInfoList.add(apiRouteInfo);
        }
        try {
            boolean result = configService.publishConfig(authRouteId, group, JSONObject.toJSONString(apiRouteInfoList));
            if (!result){
                throw new BarrierException(BarrierExceptionEnum.BARRIER_GATEWAY_ROUTE_SYNC_FAIL);
            }
        } catch (NacosException e) {
            throw new BarrierException(BarrierExceptionEnum.BARRIER_GATEWAY_ROUTE_SYNC_FAIL);
        }
    }

    @Override
    public void pushPlugin() {
        try {
            List<PluginData> pluginList = pluginDataSvc.findPluginList(null);
            String pluginJSONString = JSONObject.toJSONString(pluginList);
            log.info("--------pluginJSONString-------,:{}",pluginJSONString);
            boolean result = configService.publishConfig(pluginDataId, group, pluginJSONString);
            if (!result){
                throw new BarrierException(BarrierExceptionEnum.BARRIER_GATEWAY_PLUGIN_SYNC_FAIL);
            }
        } catch (NacosException e) {
            throw new BarrierException(BarrierExceptionEnum.BARRIER_GATEWAY_PLUGIN_SYNC_FAIL);
        }
    }

    @Override
    public void pushIpBlackWhite() {
        try {
            List<String> ipBlackList =  ipBlackWhiteSvc.findIpBlackList();

            List<String> ipWhiteList =  ipBlackWhiteSvc.findIpWhiteList();

            IpBlackWhite ipBlackWhite = new IpBlackWhite();

            ipBlackWhite.setBlack(ipBlackList);

            ipBlackWhite.setWhite(ipWhiteList);

            boolean result = configService.publishConfig(ip_black_white_Id, group, JSONObject.toJSONString(ipBlackWhite));

            if (!result){
                throw new BarrierException(BarrierExceptionEnum.BARRIER_GATEWAY_IP_BLACK_WHITE_SYNC_FAIL);
            }
        } catch (NacosException e) {
            throw new BarrierException(BarrierExceptionEnum.BARRIER_GATEWAY_IP_BLACK_WHITE_SYNC_FAIL);
        }
    }
}
